<?php


namespace App\Repositories\Gashapon;

use App\Models\MainDB\UserData;
use App\Traits\Singleton;
use App\Models\MainDB\Gashapon\LuckyStatDate as Model;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class RankRepository
{
    use Singleton;

    public function luckyRank(int $userId, string $date, int $perPage = 10)
    {
        $where = [];
        if (!empty($date)) {
            $date = explode('~', $date);
            if (count($date) == 2) {
                $where[] = ['created_at', '>=', Carbon::make(current($date))->toDateTimeString()];
                $where[] = ['created_at', '<=', Carbon::make(end($date))->toDateTimeString()];
            }
        }
        $userWhere   = $where;
        $userWhere[] = ['user_id', '=', $userId];
        $lastCount   = 0;
        $index       = 1;
        $rank        = $this->notifyCountRank($where, $perPage)->transform(function ($item) use (&$index, &$lastCount) {
            $item->index = $index;
            $item->diff  = $index == 1 ? $lastCount : $lastCount - $item->count;
            ++$index;
            $lastCount = $item->count;
            return $item;
        });
        $user        = $this->notifyCountRank($userWhere, 1);
        if (!$user) {
            $user = Model::make([
                'user_id'   => $userId,
                'user_code' => UserData::query()->where('user_id', $userId)->value('user_code'),
                'count'     => 0,
                'index'     => 0,
            ]);
        }
        $userRank    = $rank->where('user_id', $userId)->first();
        $user->index = $userRank->index ?? 0;
        if ($user->index > 0) {
            $lastRank   = $rank->where('index', $user->index - 1)->first();
            $user->diff = $user->index == 1 ? 0 : $lastRank->count - $user->count;
        } else {
            $user->diff = $lastCount - $user->count;
        }

        return Model::make(['rank' => $rank, 'self' => $user]);
    }

    public function one(array $condition = [], bool $fail = false, bool $lock = false)
    {
        $query = Model::query();
        $query->where($condition);
        if ($lock) {
            $query->lockForUpdate();
        }
        return $fail == true ? $query->firstOrFail() : $query->first();
    }

    public function find(int $id, bool $lock = false)
    {
        return $this->one(['id' => $id], true, $lock);
    }

    public function create(array $data)
    {
        $model = new Model();
        $model->fill($data);
        $model->save();
        $model->refresh();

        return $model;
    }


    protected function notifyCountRank(array $where, $perPage = 50)
    {
        $field = 'notify_count';
        $query = Model::query();
        $query->where($where);
        $query->where($field, '>', 0);
        $query->orderBy('count', 'desc');
        $query->groupBy(['user_id']);
        $query->select(['user_id', DB::raw("sum(`{$field}`) as count")]);
        $query->limit($perPage);
        return $perPage == 1 ? $query->first() : $query->with(['user'])->get();
    }
}